#include "groupCenter.h"
#include "common.h"
#include "asgkaDelAgreementThread.h"
#include "asgka_network.h"
#include "global.h"
#include "asgka_wnd_message.h"

#include <iostream>
using namespace std;

groupCenter::~groupCenter()
{
	std::map<std::string, singleGroup *>::iterator it = m_all_group_list.begin();

	while (it != m_all_group_list.end())
	{
		delete it->second;
		m_all_group_list.erase(it++);
	}
}

int groupCenter::getCountOfGroup() const
{
	return m_all_group_list.size();
}

bool groupCenter::isGroupExisted(const std::string &name) const
{
	std::map<std::string, singleGroup *>::const_iterator it = m_all_group_list.find(name);
	return (it != m_all_group_list.end());
}

singleGroup *groupCenter::getGroupByName(const std::string &name) const 
{
	std::map<std::string, singleGroup *>::const_iterator it = m_all_group_list.find(name);
	if (it != m_all_group_list.end())
		return (it->second);
	return NULL;
}

singleGroup *groupCenter::createGroup(const std::string &name, singleMember *leader) 
{
	if (!isGroupExisted(name))
	{
		singleGroup *newgroup = new singleGroup(name, leader);
		m_all_group_list.insert(stogvalType(name, newgroup));
		cout << "Group named " << name << " created" << endl;
		cout << "Group leader " << leader->getMemberName() << endl;
		std::string strlog("Group named ");
		strlog.append(name);
		strlog.append(" created, group leader : ");
		strlog.append(leader->getMemberName());
		newLog(strlog);
		notifyWnd(ASGKA_GRP_NEW, name, leader->getMemberName());
		return newgroup;
	}
	return NULL;
}

void groupCenter::releaseGroup(const std::string &name)
{
	std::map<std::string, singleGroup *>::iterator it = m_all_group_list.find(name);

	if (it != m_all_group_list.end())
	{
		delete it->second;
		m_all_group_list.erase(it);
		notifyWnd(ASGKA_GRP_DEL, name);
	}
}

void groupCenter::releaseAllGroup()
{
	std::map<std::string, singleGroup *>::iterator it = m_all_group_list.begin();

	while (it != m_all_group_list.end())
	{
		delete it->second;
		m_all_group_list.erase(it);
	}
}

void groupCenter::DelMemberFromAllGroup(const std::string &name)
{
	std::map<std::string, singleGroup *>::iterator it = m_all_group_list.begin();

	while (it != m_all_group_list.end())
	{
		if (!it->second->isAMember(name))
		{
			it++;
			continue;
		}
		if (name.compare(it->second->getGroupLeader()->getMemberName()) == 0)
		{
			std::string groupname = it->second->getGroupName();
			if (it->second != NULL)
			{
				delete it->second;
			}
			m_all_group_list.erase(it++);
			notifyWnd(ASGKA_GRP_DEL, groupname);
			continue;
		}
		else
		{
			asgkaDelAgreementThread *pThread = new asgkaDelAgreementThread(it->second, name);
			pThread->start();
			it++;
		}
	}
}

void groupCenter::DelMemberFromGroup(const std::string &group, const std::string &name)
{
	singleGroup *pGroup = getGroupByName(group);
	if (pGroup != NULL)
	{
		if (!pGroup->isAMember(name))
			return;
		if (name.compare(pGroup->getGroupLeader()->getMemberName()) == 0)
		{
			this->releaseGroup(group);
			return;
		}

		asgkaDelAgreementThread *pThread = new asgkaDelAgreementThread(pGroup, name);
		pThread->start();
	}
}

bool groupCenter::sendMessageToGroup(messageBase *msg, const std::string &groupname)
{
	bool flag = true;
	singleGroup *group = this->getGroupByName(groupname);
	
	if (group == NULL)
		return false;

	const std::map<std::string, singleMember *> *group_member = group->getAddrofMemberlist();

	std::map<std::string, singleMember *>::const_iterator it = group_member->begin();
	for (; it != group_member->end(); it++)
	{
		if (localname.compare(it->first) == 0)
			continue;

		// Send member list
		flag = flag && sendMessageToMember_tcp(msg, it->second);
	}
	return flag;
}

bool groupCenter::sendMessageToGroupLeader(messageBase *msg, const std::string &groupname)
{
	bool flag = true;
	singleGroup *group = this->getGroupByName(groupname);
	
	if (group == NULL)
		return false;

	if (localname.compare(group->getGroupLeader()->getMemberName()) == 0)
		return false;

	flag = sendMessageToMember_tcp(msg, group->getGroupLeader());
	return flag;
}
